<template>
    <div class="canvas-container">
        <canvas :canvas-id="canvasId" :id="canvasId" 
            @touchstart="handleStart"
            @touchmove="handleMove"
            @touchend="handleEnd"
            @mousedown="handleStart"
            @mousemove="handleMove"
            @mouseup="handleEnd"
            @mouseleave="handleEnd" style="background-color: transparent;"></canvas>
    </div>
    
</template>
<script lang="ts" setup>
import { ref, onMounted, defineProps } from 'vue'

const props = defineProps({
    canvasId: {
        type: String,
        default: 'myCanvas'
    }
})

let ctx = ref<CanvasRenderingContext2D | null>(null)
let isDrawing = ref(false)
let lastX = 0
let lastY = 0
let canvas = ref<HTMLCanvasElement | null>(null)
// 添加状态记录
let history = ref<ImageData[]>([])
let currentStep = ref(0)

// 添加离屏 Canvas
const offscreenCanvas = ref<HTMLCanvasElement>()
const offscreenCtx = ref<CanvasRenderingContext2D>()

const MAX_HISTORY = 30 // 最大保存步数

// 初始化画布
const initCanvas = () => {
    canvas.value = document.getElementById(props.canvasId) as HTMLCanvasElement
    if (!canvas.value) return

    // 适配高清屏
    const dpr = window.devicePixelRatio || 1
    canvas.value.width = canvas.value.offsetWidth * dpr
    canvas.value.height = canvas.value.offsetHeight * dpr
    
    ctx.value =  canvas.value.getContext('2d', { willReadFrequently: true })!
    
    if (ctx.value) {
        saveState() // 保存初始空白状态
        ctx.value.scale(dpr, dpr)
        ctx.value.strokeStyle = 'red' // 黑色画笔
        ctx.value.lineWidth = 4
        ctx.value.lineCap = 'round'
    }
}

// 触摸开始
const bindtouchstart = (e: TouchEvent) => {
    isDrawing.value = true
    const rect = (e.target as HTMLCanvasElement).getBoundingClientRect()
    lastX = e.touches[0].clientX - rect.left
    lastY = e.touches[0].clientY - rect.top
    ctx.value?.beginPath()
}

// 触摸移动
const bindtouchmove = (e: TouchEvent) => {
    if (!isDrawing.value) return
    e.preventDefault()
    
    const rect = (e.target as HTMLCanvasElement).getBoundingClientRect()
    const x = e.touches[0].clientX - rect.left
    const y = e.touches[0].clientY - rect.top
    
    if (ctx.value) {
        ctx.value.moveTo(lastX, lastY)
        ctx.value.lineTo(x, y)
        ctx.value.stroke()
    }
    
    lastX = x
    lastY = y
}
const handleStart = (e: TouchEvent | MouseEvent) => {
    isDrawing.value = true
    const rect = (e.target as HTMLCanvasElement).getBoundingClientRect()
    
    // 统一坐标获取逻辑
    const clientX = e instanceof TouchEvent ? e.touches[0].clientX : e.clientX
    const clientY = e instanceof TouchEvent ? e.touches[0].clientY : e.clientY
    
    lastX = clientX - rect.left
    lastY = clientY - rect.top
    ctx.value?.beginPath()
}

// 统一处理移动事件（支持触摸/鼠标）
const handleMove = (e: TouchEvent | MouseEvent) => {
    if (!isDrawing.value) return
    e.preventDefault()
    
    const rect = (e.target as HTMLCanvasElement).getBoundingClientRect()
    const clientX = e instanceof TouchEvent ? e.touches[0].clientX : e.clientX
    const clientY = e instanceof TouchEvent ? e.touches[0].clientY : e.clientY
    
    const x = clientX - rect.left
    const y = clientY - rect.top
    
    if (ctx.value) {
        ctx.value.moveTo(lastX, lastY)
        ctx.value.lineTo(x, y)
        ctx.value.stroke()
    }
    
    lastX = x
    lastY = y
}


// 初始化时保存初始状态
const saveState = () => {
    if (!offscreenCtx.value || !ctx.value) return
    if (history.value.length > MAX_HISTORY) {
        history.value.shift()
        currentStep.value = MAX_HISTORY
        return
    }
    
    // 使用离屏 Canvas 复制状态
    offscreenCtx.value.drawImage(canvas.value, 0, 0)
    const imageData = offscreenCtx.value.getImageData(0, 0, canvas.value.width, canvas.value.height)
    
    // 当有新操作时覆盖后续历史
    while (history.value.length > currentStep.value) {
        history.value.pop()
    }
    
    history.value.push(imageData)
    currentStep.value++
}


const handleEnd = () => {
    if( !isDrawing.value) return
    isDrawing.value = false
    saveState()  // 保存绘图状态
}

// 添加撤销方法
const undo = () => {
    if (currentStep.value <= 1) return // 保留初始状态
    
    currentStep.value--
    const prevState = history.value[currentStep.value - 1]
    ctx.value?.putImageData(prevState, 0, 0)
}


const clearCanvas = () => {
    if (ctx.value && canvas.value) {
        ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
    }
}

// 添加生成图片方法
const generateImage = (type: string = 'image/png', quality: number = 1.0) => {
    if (!canvas.value) return ''
    
    // 创建临时画布处理高清适配
    const tempCanvas = document.createElement('canvas')
    const tempCtx = tempCanvas.getContext('2d',{alpha:true})!
    
    // 保持原始比例
    const dpr = window.devicePixelRatio || 1
    tempCanvas.width = canvas.value.width / dpr
    tempCanvas.height = canvas.value.height / dpr
    
    // 绘制缩放后的内容
    tempCtx.drawImage(
        canvas.value,
        0, 0, canvas.value.width, canvas.value.height,
        0, 0, tempCanvas.width, tempCanvas.height
    )
    
    return tempCanvas.toDataURL(type, quality)
}
const isCanvasEmpty = () => {
    return currentStep.value <= 0 // 当历史步骤 <=1 时表示空白
}
const generateBlob = (): Promise<Blob> => {
  return new Promise((resolve, reject) => {
    if (!canvas.value) {
      reject(new Error('Canvas element not found'));
      return;
    }

    canvas.value.toBlob(
      (blob) => {
        blob ? resolve(blob) : reject(new Error('Failed to generate blob'));
      },
      'image/png',
      0.9
    );
  });
};

const getImageData = () => {
    if (!ctx.value) return 
    return ctx.value.getImageData(0, 0, canvas.value.width, canvas.value.height)
}

const downloadImage = async (fileName: string = 'canvas-image.png') => {
  try {
    const blob = await generateBlob()
    const url = URL.createObjectURL(blob)
    
    const a = document.createElement('a')
    a.href = url
    a.download = fileName
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  } catch (error) {
    console.error('导出图片失败:', error)
    // 如果需要可以添加 Naive UI 的通知提示
    // message.error('图片导出失败')
  }
}

onMounted(() => {
    initCanvas()
    offscreenCanvas.value = document.createElement('canvas')
    offscreenCtx.value = offscreenCanvas.value.getContext('2d')!
})
defineExpose({
    clearCanvas,
    undo,
    generateImage,
    generateBlob,
    isCanvasEmpty,
    getImageData,
    downloadImage,
    canvasArea:  ()=>canvas.value,
})
</script>
<style scoped>
.canvas-container{
    background: #fff;
} 
.canvas-container canvas{
    width: 100%;
}
</style>